(function(env) {
	//自定义节点
	class SelfNode {
		constructor(type) {
			this.type = type;
			this.attrs = [];
			this.childNodes = [];
		}
	}
	//不显示的标签
	const notJoinMap = {
		"text": true,
		"root": true
	};
	//短标签
	const shortTag = {
		"img": true,
		"input": true
	};
	//标签控制映射
	const tagControlMap = {};

	/**
	 * 检查变量
	 * @param {Object} str
	 */
	function checkAndCompile(str) {
		//标签识别
		let reg = /{{([^{#}])*?}}/g,
			//是否修改
			change = false,
			//结果
			vars = [],
			lastIndex = 0,
			regRes;
		while (regRes = reg.exec(str)) {
			vars.push({
				isStatic: true,
				value: str.substring(lastIndex, regRes.index)
			});
			if (/\{\{(.+)\}\}/.exec(regRes[0])) {
				change = true;
				vars.push({
					isStatic: false,
					scripts: myeval.compile(String(RegExp.$1))
				});
			} else {
				throw regRes[0];
			}
			lastIndex = regRes.index + regRes[0].length;
		}
		if (lastIndex < str.length) {
			vars.push({
				isStatic: true,
				value: str.substring(lastIndex, str.length)
			});
		}
		return {
			change: change,
			vars: vars
		};
	}
	/**
	 * 拼接标签
	 * @param {Object} node 节点
	 * @param {Object} sharedVarss 变量链
	 */
	function joinTag(node, sharedVarss) {
		//是否需要拼接标签
		if (node.joinData) {
			//判断节点需不需要运行
			if (node.run) {
				let res = [];
				let vars = node.vars;
				for (let i = 0; i < vars.length; i++) {
					//运行
					if (vars[i].isStatic) {
						res.push(vars[i].value);
					} else {
						res.push(myeval.run(vars[i].scripts, sharedVarss));
					}
				}
				return res.join("");
			}
			//不需要运行的直接返回
			return node.data;
		}
		//是否需要拼接标签
		if (node.joinTag) {
			let res = [];
			res.push("<");
			res.push(node.type);
			//属性
			let attrs = node.attrs,
				vars;
			//属性执行
			for (let i = 0; i < attrs.length; i++) {
				res.push(` ${attrs[i].name}="`);
				if (attrs[i].run) {
					vars = attrs[i].vars;
					for (let j = 0; j < vars.length; j++) {
						if (vars[j].isStatic) {
							res.push(vars[j].value);
						} else {
							res.push(calculate(vars[j].scripts, sharedVarss));
						}
					}
				} else {
					res.push(attrs[i].value);
				}
				res.push('" ');
			}
			//关闭
			if (node.shortTag) {
				res.push("/");
			}
			res.push(">");
			return res.join("");
		}
		return "";
	}
	/**
	 * 屬性查找
	 * @param {Object} key
	 * @param {Object} attrs
	 * @param {Object} must
	 */
	function findAttr(key, attrs, must) {
		for (let k = 0; k < attrs.length; k++) {
			if (attrs[k].name == key) {
				return attrs[k];
			}
		}
		if (must) {
			throw new Error(`参数${key}不存在`);
		}
	}
	/**
	 * 变量整理
	 * @param {Object} obj
	 */
	function paseSharedVar(obj) {
		if ("object" == (typeof obj)) {
			return obj;
		} else {
			return {
				data: obj
			};
		}
	}

	function nodesToSelfNode(childNodes) {
		let root = new SelfNode("root");
		root.joinData = false;
		root.shortTag = false;
		root.joinTag = false;
		let stack = [{
			el: childNodes,
			sup: root
		}];
		let
			//递归节点
			node,
			//临时字符串
			nodeTmpStr,
			//临时节点
			tmpNode, tmpAttr,
			//属性
			attribute, tmpEl, runCheck;
		while (node = stack.shift()) {
			tmpEl = node.el;
			if (tmpEl instanceof NodeList) {
				for (let i = 0; i < tmpEl.length; i++) {
					stack.push({
						el: tmpEl[i],
						sup: node.sup
					});
				}
			} else if (tmpEl.nodeName == "#text") {
				//是不是字符串
				nodeTmpStr = String(tmpEl.nodeValue).replace(/[\r\n\t]/g, "");
				tmpNode = new SelfNode("text");
				tmpNode.joinData = true;
				tmpNode.shortTag = true;
				tmpNode.joinTag = !(notJoinMap[tmpNode.type]);
				runCheck = checkAndCompile(nodeTmpStr);
				tmpNode.data = nodeTmpStr;
				tmpNode.run = runCheck.change;
				tmpNode._super = node.sup;
				if (runCheck.change) {
					tmpNode.vars = runCheck.vars;
				}
				node.sup.childNodes.push(tmpNode);
			} else {
				//是不是字符串
				if (tmpEl.nodeName == "#text") {
					nodeTmpStr = String(tmpEl.nodeValue).replace(/[\r\n\t]/g, "");
					if (nodeTmpStr) {
						tmpNode = new SelfNode("text");
						tmpNode.joinData = true;
						tmpNode.shortTag = true;
						tmpNode.joinTag = !(notJoinMap[tmpNode.type]);
						runCheck = checkAndCompile(nodeTmpStr);
						tmpNode.data = nodeTmpStr;
						tmpNode.run = runCheck.change;
						tmpNode._super = node.sup;
						if (runCheck.change) {
							tmpNode.vars = runCheck.vars;
						}
						node.sup.childNodes.push(tmpNode);
					}
				} else if (tmpEl.localName != null) {
					tmpNode = new SelfNode(tmpEl.localName);
					tmpNode.joinData = false;
					tmpNode.joinTag = !(notJoinMap[tmpNode.type]);
					tmpNode.shortTag = !!(shortTag[tmpNode.type]);
					//如果是节点，就解析
					if (tmpEl.attributes) {
						for (let i = 0; i < tmpEl.attributes.length; i++) {
							attribute = tmpEl.attributes[i];
							runCheck = checkAndCompile(attribute.value);
							tmpAttr = {
								name: attribute.name,
								value: attribute.value,
								run: runCheck.change
							};
							if (runCheck.change) {
								tmpAttr.vars = runCheck.vars;
							}
							tmpNode.attrs.push(tmpAttr);
						}
					}
					//子节点
					if (tmpEl.childNodes) {
						stack.push({
							el: tmpEl.childNodes,
							sup: tmpNode
						});
					}
					tmpNode._super = node.sup;
					node.sup.childNodes.push(tmpNode);
				}
			}
		}
		return root;
	}
	/**
	 * 运行节点
	 * @param {Object} nodes 节点
	 * @param {Object} mysharedVar 变量信息
	 */
	function runNodes(nodes, mysharedVar) {
		let node;
		let controlFun;
		//字符串拼接
		let joinStrTmp = "";
		for (let i = 0; i < nodes.length; i++) {
			node = nodes[i];
			if (controlFun = tagControlMap[node.type]) {
				controlFun(node.attrs, {
					findAttr: findAttr,
					sharedVars: mysharedVar,
					render: function(obj) {
						let put = obj != null;
						if (put) {
							mysharedVar.unshift(paseSharedVar(obj));
						}
						joinStrTmp += runNodes(node.childNodes, mysharedVar);
						if (put) {
							mysharedVar.shift();
						}
					}
				});
			} else {
				//开始
				joinStrTmp += joinTag(node, mysharedVar) + runNodes(node.childNodes, mysharedVar);
				//关闭
				if (node.joinTag && !node.shortTag) {
					joinStrTmp += `</${node.type}>`;
				}
			}
		}
		return joinStrTmp;
	}
	//执行单元
	class EngineUnit {
		constructor(node) {
			this._node = node;
		};
		run(data) {
			if (data == null) {
				data = env;
			}
			return runNodes([this._node], [paseSharedVar(data),window]);
		};
	}
	const domParser = new DOMParser();
	const _engine = {
		load: (str) => {
			let xmlDoc = domParser.parseFromString(`<root>${str}</root>`.replace(/[\r\n\t]/g, ""), "text/xml");
			return new EngineUnit(nodesToSelfNode(xmlDoc.childNodes[0].childNodes));
		},
		registerControlTag: (name, fun) => {
			notJoinMap[name] = true;
			tagControlMap[name] = fun;
		}
	};
	env.MyEngine = _engine;
	//基本标签的实现
	//循环
	_engine.registerControlTag("for", (attrs, util) => {
		//值
		let key = util.findAttr("var", attrs, true).value;
		//需要循环的东西
		let value = util.findAttr("items", attrs, true);
		//下一个
		let next = util.findAttr("next", attrs, false);
		//序号
		let index = util.findAttr("index", attrs, false);
		let codes = value.codeCache;
		if (!codes) {
			codes = myeval.compile(value.value);
			value.codeCache = codes;
		}
		let array = myeval.run(codes, util.sharedVars);
		if (array == null) {
			return;
		}
		let tmp = {};
		switch (typeof array) {
			case 'number':
				for (let i = 0; i < array; i++) {
					tmp[key] = i;
					if (index) {
						tmp[index.value] = i;
					}
					if (next) {
						tmp[next.value] = (array - i) > 1;
					}
					util.render(tmp);
				}
				break;
			case 'string':
				tmp[key] = array;
				if (index) {
					tmp[index.value] = 0;
				}
				if (next) {
					tmp[next.value] = false;
				}
				util.render(tmp);
				break;
			default:
				if (array.length != null && array != window) {
					let l = array.length;
					for (let i = 0; i < l; i++) {
						tmp[key] = array[i];
						if (index) {
							tmp[index.value] = i;
						}
						if (next) {
							tmp[next.value] = (l - i) > 1;
						}
						util.render(tmp);
					}
				} else {
					let ks = Object.getOwnPropertyNames(array);
					let l = ks.length;
					for (let i = 0; i < ks.length; i++) {
						tmp[key] = array[ks[i]];
						if (index) {
							tmp[index.value] = ks[i];
						}
						if (next) {
							tmp[next.value] = (l - i) > 1;
						}
						util.render(tmp);
					}
				}
		}
	});
	//if
	_engine.registerControlTag("if", (attrs, util) => {
		//值
		let test = util.findAttr("test", attrs, true);
		let codes = test.codeCache;
		if (!codes) {
			codes = myeval.compile(test.value);
			test.codeCache = codes;
		}
		if (myeval.run(codes, util.sharedVars)) {
			util.render();
		}
	});
	//with实现
	_engine.registerControlTag("with", (attrs, util) => {
		//值
		let tmp = util.findAttr("item", attrs, true);
		let codes = tmp.codeCache;
		if (!codes) {
			codes = myeval.compile(tmp.value);
			tmp.codeCache = codes;
		}
		util.render(myeval.run(codes, util.sharedVars));
	});
})(window);
